package com.bluesky.plum.uimodels.standard.components;

import java.util.ArrayList;
import java.util.List;

import com.bluesky.plum.uimodels.standard.UIComponent;
import com.bluesky.plum.uimodels.standard.components.listbox.SelectionMode;
import com.bluesky.plum.uimodels.standard.components.listbox.Selector;
import com.bluesky.plum.util.FieldUtil;

/**
 * table has column names, and data, it's something like data grid in Delphi.
 * its rows can be selected.
 * 
 * @author HZ00260
 * 
 */
public class Table<T> extends UIComponent implements Selector<T> {

	protected String[] colNames;

	protected Object[][] data;

	protected List<T> objects = new ArrayList<T>();

	protected EventListener selectChangeListener;

	protected SelectionMode selectionMode;
	protected Selector.ObjectEqualor objectEqualor = new Selector.ObjectEqualor() {
		@Override
		public boolean equals(Object obj1, Object obj2) {

			return obj1.equals(obj2);
		}
	};

	public Table() {

	}

	public List<T> getObjects() {

		return objects;
	}

	protected Object[][] generateObjectArrayForObjects() {
		if (objects.get(0).getClass().isEnum()) {
			colNames = new String[] { "name" };

			Object[][] objectsData = new Object[objects.size()][];

			for (int i = 0; i < objects.size(); i++) {

				objectsData[i] = new Object[] { objects.get(i) };

			}

			return objectsData;

		} else {

			colNames = FieldUtil.getFieldNames(objects.get(0));

			Object[][] objectsData = new Object[objects.size()][colNames.length];
			for (int i = 0; i < objects.size(); i++) {

				objectsData[i] = FieldUtil.getFieldValues(objects.get(i),
						colNames);

			}
			return objectsData;
		}
	}

	public void setObjects(List<T> objects) {

		this.objects.clear();
		for (T o : objects)
			this.objects.add(o);

		if (objects.isEmpty())
			return;

		data = generateObjectArrayForObjects();
	}

	public void addObject(T t) {
		objects.add(t);
	}

	@Override
	public String toString() {
		if (data == null)
			return super.toString();

		StringBuilder sb = new StringBuilder();
		sb.append("it is a table");

		return super.toString() + sb.toString();
	}

	public EventListener getSelectChangeListener() {
		return selectChangeListener;
	}

	public void setSelectChangeListener(EventListener selectChangeListener) {
		this.selectChangeListener = selectChangeListener;
	}

	public void selectChange() {
		if (selectChangeListener != null)
			selectChangeListener.process();
	}

	public int getSelectedIndex() {
		return -1;
	}

	public void setSelectedIndex(int index) {

	}

	public int[] getSelectedIndices() {
		return null;
	}

	public void setSelectedIndices(int[] indices) {

	}

	public SelectionMode getSelectionMode() {
		return selectionMode;
	}

	public void setSelectionMode(SelectionMode selectionMode) {
		this.selectionMode = selectionMode;
	}

	public T getSelectedValue() {
		int idx = getSelectedIndex();
		if (idx == -1)
			return null;
		else
			return objects.get(getSelectedIndex());

	}

	public T[] getSelectedValues() {
		List selectValues = new ArrayList();

		int[] indices = getSelectedIndices();
		for (int idx : indices) {
			Object o = objects.get(idx);
			selectValues.add(o);
		}

		return (T[]) selectValues.toArray();
	}

	public void setSelectedValue(T value) {
		for (int i = 0; i < objects.size(); i++) {
			if (objectEqualor.equals(objects.get(i), value)) {
				setSelectedIndex(i);
				return;
			}
		}
		throw new RuntimeException("value to set do not exist.");
	}

	public void setSelectedValues(T[] values) {
		int[] indices = new int[values.length];
		for (int i = 0; i < values.length; i++)
			indices[i] = objects.indexOf(values[i]);

		setSelectedIndices(indices);
	}

	@Override
	public void setObjectEqualor(
			com.bluesky.plum.uimodels.standard.components.listbox.Selector.ObjectEqualor objectEqualor) {
		this.objectEqualor = objectEqualor;

	}

	public Selector.ObjectEqualor getObjectEqualor() {
		return objectEqualor;
	}

}
